#include "stringcodecmanager.h"
#include <QCryptographicHash>
#include <QRegularExpression>
#include <QMap>
#include <QVector>
#include "../02-log_manager/logmanager.h"
StringCodecManager::StringCodecManager() {}


QString StringCodecManager::md5Encode(QString str) {
    QString md5;
    QByteArray bb;
    // QByteArray ba;
    // ba.append(str);
    //QByteArrayView
    bb = QCryptographicHash::hash ( str.toLatin1(), QCryptographicHash::Md5 );
    md5.append(bb.toHex());
    return md5;
}

/**
 *
 * @brief StringCodecManager::base64Encode
 * @param str
 * @return
 */
QByteArray StringCodecManager::base64Encode(QByteArray ba) {
    return ba.toBase64();
}

/**
 * toUtf8和toLatin有什么区别?
 *
 * @brief Md5Manager::base64Decode
 * @param base64String  经过base64编码的字符串,应该都是lantin1字符集的字符.
 * @return
 */
QByteArray StringCodecManager::base64Decode(QString base64String) {
    QByteArray ba = QByteArray::fromBase64(base64String.toLatin1());
    return ba;
}


/**
 * 1, &替换为&-
 * 2, 将非可打印字符串的序列,进行ModifyiedBase64Encode.
 * 2.1,将CaCbCc 得到unicdoe编码的二进制序列 Ua1 Ua2 Ub1 Ub2 Uc1 Uc2,将此二进制序列进行base64.
 * 2.2,将结果中的/转换为,
 * @brief StringCodecManager::imapUtf7Encode
 * @param string
 * @return
 */
QString StringCodecManager::imapUtf7Encode(QString string) {
    //1,将 & 替换为 &-
    static QRegularExpression reg("&");
    QString result = string.replace(reg,"&-");

    //2,
    static QRegularExpression reg2("[^\x20-\x7e]+");
    QString ret = stringReplace(result,reg2,0,[=](QString chunk)->QString{
         LogManager::debug("imapUtf7Encode","Replacer","Step",QString("chunk is: %1").arg(chunk));
        QByteArray ba = "";
        for(int i = 0; i< chunk.length() ; i++) {
            QChar qchar = chunk.at(i);
            ushort unicode = qchar.unicode();
            unsigned char high = unicode >> 8;
            unsigned char low = unicode;
            ba += high;
            ba += low;
        }
        printByteArrayInfo(ba);
        LogManager::debug("imapUtf7Encode","Replacer","Before",QString("subString is: %1").arg(chunk));
        QString base64Str = base64Encode(ba);
        //将base64结果中的/转换为,
        static QRegularExpression reg("/");
        QString result = base64Str.replace(reg,",");
        return "&"+result+"-";
    });
    return ret;


}

/**
 * 1, &-替换为&
 * 2, &xxx-,替换为xxx的 ModiyiedBase64Decode.
 * @brief StringCodecManager::imapUtf7Decode
 * @param str
 * @return
 */
QString StringCodecManager::imapUtf7Decode(QString str) {
    QRegularExpression reg("&([^-]*)-");
    // str.replace(reg,"");
    QString ret = stringReplace(str,reg,1,[=](QString chunk)->QString{

        LogManager::debug("imapUtf7Decode","Replacer","Before",QString("subString is: %1").arg(chunk));
        //长度为0,则返回&.
        if(chunk.length() == 0) {
            return "&";
        }
        else {
         //进行ImapBase64Decode.
            //将所有的 / ==> ,
            static QRegularExpression reg("/");
            QString result = chunk.replace(reg,",");

            //base64decode.
           QByteArray result1 = base64Decode(result);
            printByteArrayInfo(result1);
            QString result2 = "";
            for(int i = 0;i<result1.length();i+=2) {
                unsigned short high = (unsigned char)result1.at(i);
                unsigned short low = (unsigned char)result1.at(i+1);
                unsigned short charcode =  (high << 8) | low;
                QChar c = charcode;
                LogManager::debug("imapUtf7Decode","Base64Decode","After",QString("charcode is: %1,%2,%3").arg(high).arg(low).arg(charcode));
                result2 += c;
           }
           return result2;
        }
    });
    return ret;
}

/**
 *
 * @brief StringCodecManager::printByteArrayInfo
 * @param ba
 * @param base
 */
void StringCodecManager::printByteArrayInfo(QByteArray ba,int base) {
    QStringList list;
    for(unsigned char b : ba) {
        list << QString::number(b,base);
    }
    QString info = list.join(",");
    LogManager::debug("StringCodecManager","ByteArrayInfo","",QString("bytes is: %1").arg(info));
}


/**
 * 在原字符串中,将匹配到的字符串,进行替换.
 * 这里需要指定要捕获的部分,0代表整个匹配字符串,1代表第一个分组.
 * @brief StringCodecManager::stringReplace
 * @param str
 * @param reg
 * @param replacer
 * @return
 */
QString StringCodecManager::stringReplace(QString str,QRegularExpression reg,int capturePart, std::function<QString(QString)>replacer) {
    QRegularExpressionMatchIterator i = reg.globalMatch(str);
    QMap<MatchUnit,QString> map;
    QVector<MatchUnit *> vector;
    while (i.hasNext()) {
        QRegularExpressionMatch match = i.next();
        //第一个分组的内容.
        //捕获到的第一个分组的内容.
        QString word = match.captured(capturePart);
        QString ret = replacer(word);
        //匹配到substring的开始位置.
        int start = match.capturedStart();
        //匹配到substring的结束位置.
        // int end = match.capturedEnd();
       int length =  match.capturedLength();
        MatchUnit * unit = new MatchUnit();
       unit->pos = start;
        unit->lengh = length;
        unit->str = ret;
        //todo word replace
        vector.append(unit);
    }

    //替换操作.
    for(int i = 0; i < vector.count(); i++) {
        MatchUnit * unit = vector.at(i);
        LogManager::debug("imapUtf7Decode","stringReplace","Before",QString("%1,%2,%3").arg(unit->pos).arg(unit->lengh).arg(unit->str.length()));
        str.replace(unit->pos,unit->lengh,unit->str);
        int originLen = unit->lengh;
        int newLen = unit->str.length();
        int delta = newLen - originLen;
        //修改后面的替换的起始位置.
        for(int j = i+1;j < vector.count(); j++ ) {
            MatchUnit * unit = vector.at(j);
            unit->pos += delta;
        }
    }
    return str;
}
